package com.example.mallproduct.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.utils.PageUtils;
import com.common.utils.Query;
import com.example.mallproduct.controller.vo.Catalog2VO;
import com.example.mallproduct.dao.CategoryDao;
import com.example.mallproduct.entity.CategoryEntity;
import com.example.mallproduct.service.CategoryService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 获取类别 tree
     *
     * @return
     */
    @Override
    public List<CategoryEntity> getCategoryTree() {
        List<CategoryEntity> categoryEntityList = this.list();
//        找到顶部分类
        List<CategoryEntity> categoryEntities = categoryEntityList.stream().filter(categoryEntity -> categoryEntity.getParentCid() == 0)
                .map(categoryEntity -> {
                    categoryEntity.setChildCategoryEntityList(categoryTree(categoryEntity, categoryEntityList));
                    return categoryEntity;
                })
//                .sorted(Comparator.comparing(CategoryEntity::getSort))
                .collect(Collectors.toList());
        return categoryEntities;
    }

    /**
     * 逻辑删除类别
     *
     * @param ids
     */
    @Override
    public void removeCategoryByIds(List<Long> ids) {
        baseMapper.deleteBatchIds(ids);
    }

    /**
     * @param categoryEntity
     * @param categoryEntityList
     * @return
     */
    public List<CategoryEntity> categoryTree(CategoryEntity categoryEntity, List<CategoryEntity> categoryEntityList) {
        //找到categoryEntity的所有子分类，递归
        return categoryEntityList.stream().filter(categoryEntity1 -> categoryEntity1.getParentCid().equals(categoryEntity.getCatId()))
                .map(categoryEntity1 -> {
                    categoryEntity1.setChildCategoryEntityList(categoryTree(categoryEntity1, categoryEntityList));
                    return categoryEntity1;
                })
//                .sorted(Comparator.comparing(CategoryEntity::getSort))
                .collect(Collectors.toList());

    }

    /**
     * 查询一级分类
     *
     * @return
     */
    @Override
    public List<CategoryEntity> getLeve1Category() {
        return this.list(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));

    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 查询二三级分类
     *
     * @return
     */
    @Override
    public Map<String, List<Catalog2VO>> getCatelog2JSON() throws IOException {

        String catalogJSON = stringRedisTemplate.opsForValue().get("Catelog2JSON");
        if (StringUtils.isEmpty(catalogJSON)) {
            synchronized (this) {
                System.out.println("查数据库啊-----");
                Map<String, List<Catalog2VO>> map = getCatelog2JSONDb();
                if (null == map) {
                    //加个null缓存，防止穿透
                    stringRedisTemplate.opsForValue().set("Catelog2JSON", "null", 5, TimeUnit.SECONDS);
                } else {
                    String json = objectMapper.writeValueAsString(map);
                    //加个过期时间防止雪崩
                    stringRedisTemplate.opsForValue().set("Catelog2JSON", json, 5, TimeUnit.SECONDS);
                    return map;
                }
            }
        }
        Map<String, List<Catalog2VO>> map = objectMapper.readValue(catalogJSON, new TypeReference<Map<String, List<Catalog2VO>>>() {
        });
        return map;
    }

    /**
     * 数据库查找数据
     *
     * @return
     */
    private Map<String, List<Catalog2VO>> getCatelog2JSONDb() {
        // 获取所有的一级分类的数据
        List<CategoryEntity> leve1Category = this.getLeve1Category();
        Map<String, List<Catalog2VO>> map = leve1Category.stream().collect(Collectors.toMap(key -> key.getCatId().toString(), value -> {
            //二级分类
            List<CategoryEntity> leve2Category = this.list(new QueryWrapper<CategoryEntity>().eq("parent_cid", value.getCatId()));
            List<Catalog2VO> catalog2VOList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(leve2Category)) {
                leve2Category.forEach(val -> {
                    Catalog2VO catalog2VO = new Catalog2VO();
                    catalog2VO.setId(val.getCatId().toString());
                    catalog2VO.setName(val.getName());
                    catalog2VO.setCatalog1Id(val.getParentCid().toString());

                    //三级分类
                    List<CategoryEntity> leve3Category = this.list(new QueryWrapper<CategoryEntity>().eq("parent_cid", val.getCatId()));
                    List<Catalog2VO.Catalog3VO> catalog3VOList = new ArrayList<>();
                    if (!CollectionUtils.isEmpty(leve3Category)) {
                        leve3Category.forEach(val3 -> {
                            Catalog2VO.Catalog3VO catalog3VO = new Catalog2VO.Catalog3VO();
                            catalog3VO.setId(val3.getCatId().toString());
                            catalog3VO.setName(val3.getName());
                            catalog3VO.setCatalog2Id(val3.getParentCid().toString());
                            catalog3VOList.add(catalog3VO);
                        });
                        catalog2VO.setCatalog3List(catalog3VOList);
                    }
                    catalog2VOList.add(catalog2VO);
                });

            }

            return catalog2VOList;
        }));
        return map;
    }
}